package gttp.nspa.client.adm.ui;

import gttp.nspa.client.adm.Dict;
import gttp.nspa.client.adm.activity.IBillingList;
import gttp.nspa.shared.om.Billing;
import gttp.nspa.shared.om.Billing.Status;
import gttp.nspa.shared.om.Customer;
import gttp.nspa.shared.om.IOrder;
import gttp.nspa.shared.om.Locker;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.XTemplates;
import com.sencha.gxt.core.client.util.Margins;
import com.sencha.gxt.core.client.util.Padding;
import com.sencha.gxt.widget.core.client.Portlet;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.BoxLayoutContainer.BoxLayoutData;
import com.sencha.gxt.widget.core.client.container.PortalLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VBoxLayoutContainer;
import com.sencha.gxt.widget.core.client.container.VBoxLayoutContainer.VBoxLayoutAlign;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;

public class BillingList implements IBillingList {

    public static final String NAME      = "Billings";
    public static final int    COL_COUNT = 4;

    interface Messages extends XTemplates {

        @XTemplate("{time:date(\"HH:mm\")}")
        SafeHtml headerText(Date time);

        @XTemplate("{time:date(\"HH:mm\"} - {timeEnd:date(\"HH:mm\")}")
        SafeHtml headerTextWithEndTime(Date time, Date timeEnd);
    }

    Messages MESSAGE = GWT.create(Messages.class);

    private class Billet extends Portlet {

        final long billId;

        TextButton btnLocker;
        TextButton btnCustomer;
        TextButton btnOrders;
        TextButton btnBillPaid;

        Billet(Billing billing) {
            this(billing.getId());
            update(billing);
        }

        Billet(long id) {
            this.billId = id;

            BoxLayoutData bld = new BoxLayoutData(new Margins(0, 0, 4, 0));
            VBoxLayoutContainer con = new VBoxLayoutContainer();
            con.setPadding(new Padding(4));
            con.setVBoxLayoutAlign(VBoxLayoutAlign.STRETCH);

            btnLocker = new TextButton();
            btnLocker.addSelectHandler(new SelectHandler() {

                public void onSelect(SelectEvent event) {
                    presenter.onSelectingLocker(billId, (String) btnLocker.getData("code"));
                }
            });
            con.add(btnLocker, bld);

            btnCustomer = new TextButton();
            btnCustomer.addSelectHandler(new SelectHandler() {

                public void onSelect(SelectEvent event) {
                    presenter.onSelectingCustomer(billId, (String) btnCustomer.getData("alias"));
                }
            });
            con.add(btnCustomer, bld);

            btnOrders = new TextButton("Orders");
            btnOrders.addSelectHandler(new SelectHandler() {

                public void onSelect(SelectEvent event) {
                    presenter.onViewingOrders(billId);
                }
            });
            con.add(btnOrders, bld);

            btnBillPaid = new TextButton("PAID");
            btnBillPaid.addSelectHandler(new SelectHandler() {

                public void onSelect(SelectEvent event) {
                    presenter.onPayingBill(billId);
                }
            });
            con.add(btnBillPaid, bld);

            setWidget(con);
        }

        void update(Billing billing) {
            long time = billing.getTime();
            Long end = billing.getTimeEnd();
            SafeHtml heading;
            if (end != null) {
                heading = MESSAGE.headerTextWithEndTime(new Date(time), new Date(end.longValue()));
            } else {
                heading = MESSAGE.headerText(new Date(time));
            }
            setHeadingHtml(heading);

            String locker = billing.getLocker();
            btnLocker.setData("code", locker);
            btnLocker.setText(locker != null ? Dict.LOCKER.get(locker).getName() : "-");

            String alias = billing.getAlias();
            btnCustomer.setData("alias", alias);
            btnCustomer.setText(alias != null ? alias : "-");
        }
    }

    private PortalLayoutContainer con;

    private Map<Long, Billet>     billets;
    private Presenter             presenter;

    public BillingList() {
        billets = new HashMap<Long, BillingList.Billet>();

        con = new PortalLayoutContainer(COL_COUNT);
        for (int i = 0; i < COL_COUNT; i++) {
            con.setColumnWidth(i, 100 / COL_COUNT);
        }

        addNewBillButton();
    }

    private void addNewBillButton() {
        TextButton btnNewBill = new TextButton("NEW BILL");
        btnNewBill.addSelectHandler(new SelectHandler() {

            public void onSelect(SelectEvent event) {
                presenter.onAddingNewBill();
            }
        });
        con.insert(btnNewBill, 0, 0);
    }

    private void addBillet(Billing bill) {
        Billet billet = new Billet(bill);
        billets.put(bill.getId(), billet);
        con.add(billet, (billets.size() - 1) % COL_COUNT);
    }

    private void updateBillet(Billing billing) {
        Billet billet = billets.get(billing.getId());
        if (billet != null) {
            billet.update(billing);
        }
    }

    private void removeBillet(long billId) {
        Billet billet = billets.remove(billId);
        if (billet != null) {
            con.remove(billet, con.getPortletColumn(billet));
        }
    }

    public void reload(Long from, Long to, Status billStatus) {
        con.clear();
        billets.clear();

        addNewBillButton();

        presenter.onListBillRequest(from, to, billStatus, new AsyncCallback<List<Billing>>() {

            public void onSuccess(List<Billing> result) {
                for (Billing bill : result) {
                    addBillet(bill);
                }
            }

            public void onFailure(Throwable caught) {
            }
        });
    }

    public void setPresenter(Presenter presenter) {
        this.presenter = presenter;
    }

    public void billAdded(Billing bill) {
        addBillet(bill);
    }

    public void billModified(Billing bill) {
        updateBillet(bill);
    }

    public void billRemoved(Billing bill) {
        removeBillet(bill.getId());
    }

    public void lockerSelected(long billId, Locker locker) {
    }

    public void customerSelected(long bilId, Customer customer) {
    }

    public void orderAdded(long billId, IOrder order) {
    }

    public void orderModified(long billId, IOrder order) {
    }

    public void orderCancelled(long billId, IOrder order) {
    }

    public Widget asWidget() {
        return con;
    }

    public String toString() {
        return NAME;
    }

}
